原生态HTML文件上传与下载

文件下载

传统的文件下载有两种方法:

  1. 使用<a/>标签,href属性直接连接到服务器的文件路径
  2. window.location.href="url"

这两种方法效果一样。但有个很大的问题,如果下载出现异常(连接路径失效、文件不存在、网络问题等),会导致原本的页面被覆盖掉,显示404等错误信息。

大致的优化思路如下:

  1. 使用<a/>标签HTML5新的属性download。
  2. 使用<iframe><iframe/>元素进行下载。
  3. 使用ajax、axios、fetch等方法异步下载。
  4. 使用websocket下载。

我们来逐一分析:

  1.  <a/>标签的download属性,需要和href一起用,download的作用是为下载的文件赋文件名。
    • 如果服务端没有指定文件名,就以此属性规定的名称命名。
    • 如果下载出现异常,该属性的存在能够保证页面不会出问题。
    • 如果服务端返回的不是文件、而是字符,如果download=‘’error.txt”,能够通过打开此文件查看到返回的文本信息。
  2. <iframe>标签可以做到在现有的页面下,内嵌一个子页面。当用户点击文件下载时,将隐藏的iframe元素的src属性指向文件下载路径。
    • 如果没有异常,文件将会直接下载。
    • 如果出现异常,iframe子页面会报错,父页面不会受任何影响。
  3. 使用异步请求进行下载。
    • 在网上看了看,大致的流程是:发送异步请求时设置responseType为blob,即接收流数据为blob对象保存在内存中。接收完成后,生成链接地址(1.通过FileReader对象将blob对象生成base64编码 2.通过URL.createObjectURL生成指向文件内存的链接),写入<a/>标签的href属性,然后模拟点击<a/>按标签实现下载。
    • 此方法最大的问题是,因无法直接操作磁盘,故接收的文件必须先存放在内存中(且只有传输完成后才能构建blob对象),才能转化成文件。因此,大文件的下载可能会把你的浏览器挤爆。
  4. 使用websocket下载。
    • 需要额外开启websocket服务,此方法未做实践。

总结以上方法,最推荐前两种,方便简单。

附上后端Django代码(适用于前两种方法):

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

def syncDownLoad(request):

    "文件下载"

    print("同步下载文件")

    startTime = time.time()

 

    def file_iterator(file, chunk_size=1024):

        with open(file"rb") as f:

            while True:

                = f.read(chunk_size)

                if c:

                    yield c

                else:

                    endTime = time.time()

                    print("传输时间", endTime - startTime)

                    break

 

    fileRoute = "/static/files/2018/12/18/第四章(1)学习动机概述.mp4"

    fileName = "第四章(1)学习动机概述.mp4"

    route = os.path.dirname(os.path.dirname(__file__)) + fileRoute

    if os.path.exists(route):  # 如果存在文件

        response = StreamingHttpResponse(file_iterator(route))

        # response['Content-Type'] = 'application/octet-stream'

        response['Content-Type'= 'text/html'

        response['Content-Disposition'= 'attachment;filename="{0}"'.format(fileName).encode("utf-8")

        return response

    else:

        return HttpResponse("cannot find file")

参考链接:

https://scarletsky.github.io/2016/07/03/download-file-using-javascript/

https://my.oschina.net/watcher/blog/1525962

 

文件上传

 概述

文件上传需要处理的问题有:

1.多文件上传  2.异步上传  3.拖拽上传  4.上传限制(限制大小、类型) 5.显示上传进度、上传速度、中途取消上传  6.预览文件

HTML DEMO

1

2

<input type="file" id="file" name="myfile" onchange="onchanges()" multiple="multiple"/>

<input type="button" onclick="SerialUploadFile()" value="上传"/>

一、多文件上传

1

<input type="file" id="file" name="myfile" multiple="multiple"/> <!-- multiple属性 -->

二、异步上传

通过ajax等方式异步上传,FormData对象支持传输文件。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

function UploadFile() {

  var fileObj = document.getElementById("file").files;  // js 获取文件对象(FileList对象)

 

  // FormData 对象

  var form = new FormData();

  form.append("author""xueba");             // 可以增加表单数据

  for (let i = 0; i < fileObj.length; i++)

  {

     form.append("file", fileObj[i]);        // 文件对象

  }

 

     $.ajax({

        url: "/file_upload/",

        type: "POST",

        async: true,      // 异步上传

        data: form,

        contentType: false// 必须false才会自动加上正确的Content-Type

        processData: false// 必须false才会避开jQuery对 formdata 的默认处理。XMLHttpRequest会对 formdata 进行正确的处理

        success: function (data) {

           data = JSON.parse(data);

           data.forEach((i)=>{

              console.log(i.code,i.file_url);

           });

        },

        error: function () {

           alert("aaa上传失败!");

        },

     });

 

}

三、拖拽上传

默认文本、图像和链接可以被拖动。其它的元素想要被拖动,只需为标签加一个draggable="true"属性

1

<div draggable="true"><div/>

 HTML5 API drag 和 drop

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

被拖动元素发生的事件

    dragstart    被拖动元素开始拖动时

    drag         正在被拖动时

    dragend      取消拖拽时

     

目标元素发生的事件(当某元素被绑定以下事件就变成了目标元素)

    dragenter    拖动元素进入目标上触发

    dragover     拖动元素在目标元素上移动触发

    dragleave    拖动元素离开目标时触发

    drop         拖动元素在目标上释放触发,这时不会触发dragleave

 

注意:

    1.目标元素默认不能够被拖放drop,要在dragover事件中取消默认事件(e.preventDefault())

    2.有些元素(img)被拖放后,默认以链接形式打开,要在drop事件中取消默认事件(e.preventDefault())

        【火狐浏览器可能不顶用,需要再加event.stopPropagation()】

 

dataTransfer(事件对象属性(对象))

    数据交换:只是简单的拖拽没有意义,我们还需要数据交换,即被拖动元素和目标元素之间的数据交换。

    方法:

        setData(key,value)  设置数据(key和value都必须是string类型)

        getData(key)        获取数据

        clearData()         清除数据(不传参清空所有数据)

        setDragImage(imgElement,x,y)      设置元素移动过程中的图像(参数:图像元素,xy表示图像内的偏移量)

    属性:

        dropEffect  表示被拖动元素可以执行哪一种放置行为(一般在dragover事件内设置)

            none禁止放置(默认值)  

            move移动到新的位置  

            copy复制到新的位置

            link

        effectAllowed  用来指定拖动时被允许的行为(一般无需设置)

            copy,move,link,copyLink,copyMove,linkMove,all,none,uninitialized默认值,相当于all.

        files    FileList对象。如果拖动的不是文件,此为空列表    

        items    返回DataTransferItems对象,该对象代表了拖动数据。

        types    返回一个DOMStringList对象,该对象包括了存入dataTransfer中数据的所有类型。

     

     

    注意:

        1.如果拖拽了文本,浏览器会自动调用setData(),设置对应文本数据

参考链接:

https://developer.mozilla.org/zh-CN/docs/Web/API/HTML_Drag_and_Drop_API

https://developer.mozilla.org/zh-CN/docs/Web/API/DataTransfer

https://www.zhangxinxu.com/wordpress/2018/09/drag-drop-datatransfer-js/

http://www.sohu.com/a/198973397_291052

四、上传限制

1

<input type="file"  accept="image/*" /> 接收全部格式的图片

此外,获取到的File对象中有type属性可以得知文件类型,size属性的得知文件大小

五、上传进度、上传速度、中途取消上传

原生API

1

2

3

4

5

6

7

8

9

10

11

12

xhr.onload = function(e){};//上传请求完成

xhr.onerror = function(e){};//上传异常

xhr.upload.onloadstart = function(e){};//开始上传

xhr.upload.onprogress =function(e){};//上传进度  这个方法会在文件每上传一定字节时调用

 

e.loaded//表示已经上传了多少byte的文件大小

e.total//表示文件总大小为多少byte

通过这两个关键的属性就可以去计算 上传进度与速度

 

xhr.onreadystatechange = function(){}//当xhr的状态(上传开始,结束,失败)变化时会调用 该方法可以用来接收服务器返回的数据

 

中途取消上传 xhr.abort();

单文件上传 或 多文件串行上传 Demo:(该Demo只会有一个进度条,显示上传总进度。对应“异步上传”的代码)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

xhr.upload.addEventListener("progess",progessSFunction,false); // 上传过程中显示进度和速度

 

function progressSFunction(e) {

      var progressBar = document.getElementById(`pro`);

      var percentageDiv = document.getElementById(`per`);

      if (e.lengthComputable) // lengthComputable表示进度信息是否可用

      {

         progressBar.max = e.total;

         progressBar.value = e.loaded;

         let speed = (e.loaded - progress[0].last_laoded) / (e.timeStamp - progress[0].last_time) + " bytes/s";

         let percent = Math.round(e.loaded / e.total * 100) + "%";

         progress[0].last_laoded = e.loaded, progress[0].last_time = e.timeStamp;

         percentageDiv.innerHTML = percent + " " + speed;

      }

   }

多文件并行上传进度显示:(多个进度条,分别上传)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

// 多文件并行上传

    function ParallelUploadFile() {

      last_laoded = 0;

      last_time = (new Date()).getTime();

 

      var fileObj = document.getElementById("file").files;  // js 获取文件对象

      for (let k = 0; k < fileObj.length; k++)

      {

 

         let domStr = `<div> ${fileObj[k].name},大小${fileObj[k].size}字节

                        <progress class='progressBar' id='pro${k}' value='' max=''></progress>

                        <span class='percentage' id='per${k}'></span>

                        </div>`;

         $("body").append(domStr);

 

         // FormData 对象

         var form = new FormData();

         form.append("author""xueba");             // 可以增加表单数据

         form.append("csrfmiddlewaretoken", $("[name = 'csrfmiddlewaretoken']").val());

         form.append("file", fileObj[k]);

 

 

         // XMLHttpRequest 对象

         {#var xhr = new XMLHttpRequest();#}

         {#xhr.open("post", "/file_upload/", true);#}

         {#xhr.onload = function () {#}

         {#   alert("上传完成!");#}

         {# };#}

         {#xhr.upload.addEventListener("progress", progressFunction, false);#}

         {#xhr.send(form);#}

 

         // jQuery ajax

         $.ajax({

            url: "/file_upload/",

            type: "POST",

            async: true,      // 异步上传

            data: form,

            contentType: false// 必须false才会自动加上正确的Content-Type

            processData: false// 必须false才会避开jQuery对 formdata 的默认处理。XMLHttpRequest会对 formdata 进行正确的处理

            xhr: function () {

               let xhr = $.ajaxSettings.xhr();

               xhr.upload.addEventListener("progress", (e) => {progressPFunction(e, k)}, false);

               xhr.upload.onloadstart = (e) => {

                  progress[k] = {

                     last_laoded: 0,

                     last_time: e.timeStamp,

                  };

               };

               xhr.upload.onloadend = () => {

                  delete progress[k];

               };

               return xhr;

            },

            success: function (data) {

               data = JSON.parse(data);

               data.forEach((i) => {

                  console.log(i.code, i.file_url);

               });

            },

            error: function () {

               alert("aaa上传失败!");

            },

         });

      }

 

    }

六、预览文件

预览图片

1

2

3

4

5

6

7

8

9

10

11

12

13

function onchanges() { // input file绑定onchange事件

   let files = document.getElementById("file").files;

   if(files[0].type.indexOf("image")>-1)

   {

      let read = new FileReader();

      read.onload = function(e) { // 读取操作完成时触发

         let img = new Image();

         img.src = e.target.result; // 将base64编码赋给src属性

   $("body")[0].appendChild(img);

      };

      read.readAsDataURL(files[0]); // 读取文件转化成base64编码

   }

七、前后端汇总Demo

前端

HTML

1

2

<input type="file" id="file" name="myfile" onchange="onchanges()" multiple="multiple"/>

<input type="button" onclick="SerialUploadFile()" value="上传"/>

JavaScript

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

let progress = {};

let last_laoded;

let last_time;

 

function onchanges() {

   let files = document.getElementById("file").files;

   console.log(`共${files.length}个文件`);

   let countSize = 0;

   for (let i = 0; i < files.length; i++) {

      console.log(`${files[i].name}  大小${files[i].size}`);

      countSize += files[i].size;

   }

   console.log(`共计占用${countSize}字节`);

   if (files[0].type.indexOf("image") > -1)

   {

      let read = new FileReader();

      read.onload = function (e) { // 读取操作完成时触发

         let img = new Image();

         img.src = e.target.result; // 将base64编码赋给src属性

         $("body")[0].appendChild(img);

 

      };

      read.readAsDataURL(files[0]); // 读取文件转化成base64编码

   }

}

 

 // 多文件并行上传

 function ParallelUploadFile() {

   last_laoded = 0;

   last_time = (new Date()).getTime();

 

   var fileObj = document.getElementById("file").files;  // js 获取文件对象

   for (let k = 0; k < fileObj.length; k++)

   {

 

      let domStr = `<div> ${fileObj[k].name},大小${fileObj[k].size}字节

                     <progress class='progressBar' id='pro${k}' value='' max=''></progress>

                     <span class='percentage' id='per${k}'></span>

                     </div>`;

      $("body").append(domStr);

 

      // FormData 对象

      var form = new FormData();

      form.append("author""xueba");             // 可以增加表单数据

      form.append("csrfmiddlewaretoken", $("[name = 'csrfmiddlewaretoken']").val());

      form.append("file", fileObj[k]);

 

 

      // XMLHttpRequest 对象

      {#var xhr = new XMLHttpRequest();#}

      {#xhr.open("post", "/file_upload/", true);#}

      {#xhr.onload = function () {#}

      {#   alert("上传完成!");#}

      {# };#}

      {#xhr.upload.addEventListener("progress", progressFunction, false);#}

      {#xhr.send(form);#}

 

      // jQuery ajax

      $.ajax({

         url: "/file_upload/",

         type: "POST",

         async: true,      // 异步上传

         data: form,

         contentType: false// 必须false才会自动加上正确的Content-Type

         processData: false// 必须false才会避开jQuery对 formdata 的默认处理。XMLHttpRequest会对 formdata 进行正确的处理

         xhr: function () {

            let xhr = $.ajaxSettings.xhr();

            xhr.upload.addEventListener("progress", (e) => {progressPFunction(e, k)}, false);

            xhr.upload.onloadstart = (e) => {

               progress[k] = {

                  last_laoded: 0,

                  last_time: e.timeStamp,

               };

            };

            xhr.upload.onloadend = () => {

               delete progress[k];

            };

            return xhr;

         },

         success: function (data) {

            data = JSON.parse(data);

            data.forEach((i) => {

               console.log(i.code, i.file_url);

            });

         },

         error: function () {

            alert("aaa上传失败!");

         },

      });

   }

 

 }

 

// 多文件串行上传

function SerialUploadFile() {

 

 

   var fileObj = document.getElementById("file").files;  // js 获取文件对象

 

   let domStr = `<div>

                     <progress class='progressBar' id='pro' value='' max=''></progress>

                     <span class='percentage' id='per'></span>

                 </div>`;

   $("body").append(domStr);

 

   // FormData 对象

   var form = new FormData();

   form.append("author""xueba");             // 可以增加表单数据

   for (let i = 0; i < fileObj.length; i++)

   {

      form.append("file", fileObj[i]);        // 文件对象

   }

 

   // jQuery ajax

   $.ajax({

      url: "/file_upload/",

      type: "POST",

      async: true,      // 异步上传

      data: form,

      contentType: false// 必须false才会自动加上正确的Content-Type

      processData: false// 必须false才会避开jQuery对 formdata 的默认处理。XMLHttpRequest会对 formdata 进行正确的处理

      xhr: function () {

         let xhr = $.ajaxSettings.xhr();

         xhr.upload.addEventListener("progress", progressSFunction, false);

         xhr.upload.onloadstart = (e) => {

            progress[0] = {

              last_laoded: 0,

              last_time: e.timeStamp,

           };

            console.log("开始上传",progress);

         };

         xhr.upload.onloadend = () => {

            delete progress[0];

            console.log("结束上传",progress);

         };

         return xhr;

      },

      success: function (data) {

         data = JSON.parse(data);

         data.forEach((i) => {

            console.log(i.code, i.file_url);

         });

      },

      error: function () {

         alert("aaa上传失败!");

      },

   });

 

}

 

// jQuery版本进度条

function Progressbar(e) {

   var bar = $("#progressBar"); // 进度条

   var num = $("#percentage");  // 百分比

   if (e.lengthComputable) {

      bar.attr("max", e.total);

      bar.attr("value", e.loaded);

      num.text(Math.round(e.loaded / e.total * 100) + "%");

   }

 

}

 

 

 // 原生js版 并行进度条

 function progressPFunction(e, k) {

   var progressBar = document.getElementById(`pro${k}`);

   var percentageDiv = document.getElementById(`per${k}`);

   if (e.lengthComputable) {

      progressBar.max = e.total;

      progressBar.value = e.loaded;

      let speed = (e.loaded - progress[k].last_laoded) / (e.timeStamp - progress[k].last_time) + " bytes/s";

      let percent = Math.round(e.loaded / e.total * 100) + "%";

      progress[k].last_laoded = e.loaded, progress[k].last_time = e.timeStamp;

      percentageDiv.innerHTML = percent + " " + speed;

      console.log(speed);

   }

 }

 

// 原生js 串行进度条

function progressSFunction(e) {

   var progressBar = document.getElementById(`pro`);

   var percentageDiv = document.getElementById(`per`);

   if (e.lengthComputable) // lengthComputable表示进度信息是否可用

   {

      progressBar.max = e.total;

      progressBar.value = e.loaded;

      let speed = (e.loaded - progress[0].last_laoded) / (e.timeStamp - progress[0].last_time) + " bytes/s";

      let percent = Math.round(e.loaded / e.total * 100) + "%";

      progress[0].last_laoded = e.loaded, progress[0].last_time = e.timeStamp;

      percentageDiv.innerHTML = percent + " " + speed;

   }

}

Django后端

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

def file_upload(request):

    "ajax文件上传功能"

    resList, fileList = [], request.FILES.getlist("file")

    dir_path = 'static/files/{0}/{1}/{2}'.format(time.strftime("%Y"),time.strftime("%m"),time.strftime("%d"))

    if os.path.exists(dir_path) is False:

        os.makedirs(dir_path)

    for file in fileList:

        file_path = '%s/%s' % (dir_path, file.name)

        file_url = '/%s/%s' % (dir_path, file.name)

        res = {"code"0"file_url": ""}

        with open(file_path, 'wb') as f:

            if == False:

                res['code'= 1

            for chunk in file.chunks(): # chunks()代替read(),如果文件很大,可以保证不会拖慢系统内存

                f.write(chunk)

        res['file_url'= file_url

        resList.append(res)

    return HttpResponse(json.dumps(resList))

参考:

https://www.cnblogs.com/potatog/p/9342448.html

https://www.w3cmm.com/ajax/progress-events.html

文章来源:https://www.cnblogs.com/V587Chinese/p/11371380.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/473264.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Jquery 常用总结

获取元素的宽度: 如果用$(ele).attr("width")获取的值不带px 如果用$(ele).css("width")获取的值带px //获取鼠标坐标 $(function() { $("#Button2").click(function(event) { alert(event.p…

LeetCode 1187. 使数组严格递增(DP)*

文章目录1. 题目2. 解题1. 题目 给你两个整数数组 arr1 和 arr2&#xff0c;返回使 arr1 严格递增所需要的最小「操作」数&#xff08;可能为 0&#xff09;。 每一步「操作」中&#xff0c;你可以分别从 arr1 和 arr2 中各选出一个索引&#xff0c;分别为 i 和 j&#xff0c…

用Python进行屏幕截图,只用两行代码搞定

一、计算机中如何进行屏幕截图呢&#xff1f; 1、全屏截图 按下键盘中的‘PRTSC’或者‘Print Screen’键&#xff0c;即可实现全屏截图&#xff08;不同键盘位置和名称可能不同&#xff09;。此时&#xff0c;并不能看到效果&#xff0c;只是将截图保存在粘贴板中&#xff0…

POJ 2075 Tangled in Cables (c++/java)

http://poj.org/problem?id2075 题目大意&#xff1a; 给你一些人名&#xff0c;然后给你n条连接这些人名所拥有的房子的路&#xff0c;求用最小的代价求连接这些房子的花费是否满足要求。 思路&#xff1a; 昨天20分钟的题&#xff0c;输入不小心写错了- -|||||看世界杯半场休…

利用nginx建立windows软连,实现IP访问文件

一、运行nginx 1、首先下载nginx&#xff0c;下载地址&#xff1a;https://www.lanzous.com/ianm7tg 2、解压文件如图&#xff1a; 3、运行nginx.exe&#xff0c;浏览器运行电脑ip地址&#xff0c;如图&#xff1a; 二、cmd管理员权限 运行中输入“cmd”&#xff0c;按住shi…

LeetCode 1263. 推箱子(BFS+DFS / 自定义哈希set)

文章目录1. 题目2. 解题2.1 超时解2.2 BFS DFS1. 题目 「推箱子」是一款风靡全球的益智小游戏&#xff0c;玩家需要将箱子推到仓库中的目标位置。 游戏地图用大小为 n * m 的网格 grid 表示&#xff0c;其中每个元素可以是墙、地板或者是箱子。 现在你将作为玩家参与游戏&a…

深入浅出Java回调机制

前几天看了一下Spring的部分源码&#xff0c;发现回调机制被大量使用&#xff0c;觉得有必要把Java回调机制的理解归纳总结一下&#xff0c;以方便在研究类似于Spring源码这样的代码时能更加得心应手。 注&#xff1a;本文不想扯很多拗口的话来充场面&#xff0c;我的目的是希望…

前端:实现div等块元素添加X轴滚动显示(Y轴不滚动)

一、建立外盒子与内盒子 原生态代码&#xff1a; <div class"tol_dev"><div class"dev_li"></div><div class"dev_li"></div><div class"dev_li"></div><div class"dev_li"…

2020年学习总结

文章目录1. CSDN 博客数据2. 基础算法练习3. 机器学习4. 深度学习5. MySQL6. 总结和展望时间过得很快&#xff0c;2020结束了&#xff01; 写个流水账&#xff0c;记录一下。 1. CSDN 博客数据 截个图对比下&#xff1a; 2019年终2020年终 2. 基础算法练习 LeetCode 刷题 …

npm全局环境变量配置及解决VsCode使用时遇到的问题

一、npm全局环境变量配置 1、我们要先配置npm的全局模块的存放路径以及cache的路径 例如我希望将以上两个文件夹放在NodeJS的主目录下&#xff0c;便在NodeJs下建立”node_global”及”node_cache”两个文件夹。如下图 2、cmd 中输入如下命令 npm config set prefix “d:\no…

Android菜鸟如何学习Android系统开发?

如何做好Android学习前的准备? 如果你已经确定了学习Android的目标&#xff0c;那么&#xff0c;应该提前做好哪些工作、先打下哪些基础呢? 首先&#xff0c;你最好先熟悉一门编程语言&#xff0c;现在大学里面和计算机相关的专业甚至理工类专业一般都会开设C语言课程&#x…

关于Django中JsonResponse返回中文字典编码错误的解决方案

遇到这样一个问题&#xff0c;返回的json不是中文 def get_json(request):return JsonResponse({"res": "成功"}) 结果&#xff1a; {"res": "\u6210\u529f"} 解决方案&#xff1a;JsonResponse(data, json_dumps_params{ensure_a…

LeetCode 668. 乘法表中第k小的数(二分查找)

文章目录1. 题目2. 解题1. 题目 几乎每一个人都用 乘法表。但是你能在乘法表中快速找到第k小的数字吗&#xff1f; 给定高度m 、宽度n 的一张 m * n的乘法表&#xff0c;以及正整数k&#xff0c;你需要返回表中第k 小的数字。 例 1&#xff1a; 输入: m 3, n 3, k 5 输出…

获取类类型

//获得类类型的两种方式 1、 Class cls1 Role.class; 2、 Class cls2 Class.forName("yui.Role"); 注意第二种方式中&#xff0c;forName中的参数一定是完整的类名&#xff08;包名类名&#xff09;&#xff0c;并且这个方法需要捕获异常。 现在得到cl…

VUE:解决判断网页端与手机端情况下,横竖屏无法判断的问题

一、需求&#xff1a; 第一步&#xff1a;判断是网页端还是手机端 第二步&#xff1a;判断手机端&#xff0c;手机是横屏显示还是竖屏显示 二、解决方法&#xff1a; 监听网页端还是手机端 监听显示页面宽高变化 三、代码如下&#xff1a; methods: {_isMobile() {let f…

天池 在线编程 寻找比周围都大的点(模拟)

文章目录1. 题目2. 解题1. 题目 https://tianchi.aliyun.com/oj/245679029019779851/254275128279634587 给一个n*m大小的矩阵&#xff0c;寻找矩阵中所有比邻居&#xff08;上下左右&#xff0c;对角也算&#xff0c;不考虑边界就是8个咯&#xff09;都严格大的点。 返回一个…

前端笔试题总结---持续更新

写在前面&#xff1a;。。。。 1字符串逆序 function reverse(str){return str.split("").reverse().join("");//直接用函数var str1"";//从后向前输出for(var istr.length-1;i>0;i--){str1str[i];}return str1;var lenstr.length;//字符串原…

[原创][R语言]股票分析实战[4]:周级别涨幅趋势的相关性

[简介] 常用网名: 猪头三 出生日期: 1981.XX.XX QQ联系: 643439947 个人网站: 80x86汇编小站 https://www.x86asm.org 编程生涯: 2001年~至今[共22年] 职业生涯: 20年 开发语言: C/C、80x86ASM、PHP、Perl、Objective-C、Object Pascal、C#、Python 开发工具: Visual Studio、D…

前端:实现手机左右滑动效果

需求&#xff1a;手机可以左右滑动&#xff0c;显示商品或者div信息 原理&#xff1a;建立两个盒子&#xff0c;一个是可以看到的手机屏幕盒子&#xff0c;一个是自己设定好的盒子&#xff0c;左右滑动&#xff0c;只显示与手机屏幕盒子交集的部分 代码&#xff1a; <div …

天池 在线编程 双向取数(博弈DP)

文章目录1. 题目2. 解题1. 题目 https://tianchi.aliyun.com/oj/245679029019779851/254275128279634585 有一个长度为n的数列arr&#xff0c; 甲乙两个人每次可以从头或者从末尾取一个数&#xff0c;双方都想让自己取数之和尽量多&#xff0c; 甲先取数&#xff0c;问甲乙在…