阿里云主机折上折
  • 微信号
Current Site:Index > File operations (uni.uploadFile, uni.downloadFile)

File operations (uni.uploadFile, uni.downloadFile)

Author:Chuan Chen 阅读数:19363人阅读 分类: uni-app

File Upload (uni.uploadFile)

uni.uploadFile is an API in uni-app used to upload local resources to a server. It encapsulates the underlying upload interfaces of platforms like WeChat Mini Programs and H5, providing a unified calling method. The upload process supports operations such as monitoring progress and canceling uploads.

Basic usage:

uni.chooseImage({
  success: (res) => {
    const tempFilePaths = res.tempFilePaths
    uni.uploadFile({
      url: 'https://example.com/upload',
      filePath: tempFilePaths[0],
      name: 'file',
      formData: {
        'user': 'test'
      },
      success: (uploadRes) => {
        console.log(uploadRes.data);
      }
    });
  }
});

Key parameter descriptions:

  • url: Developer server address
  • filePath: Path of the file resource to upload
  • name: Key corresponding to the file
  • formData: Additional form data in the HTTP request

Common scenarios in actual development:

  1. Multi-file upload implementation:
const uploadTasks = []
files.forEach((file, index) => {
  const task = uni.uploadFile({
    url: 'https://example.com/upload',
    filePath: file.path,
    name: 'file_' + index,
    success: () => {
      console.log(`File ${index} uploaded successfully`)
    }
  })
  uploadTasks.push(task)
})

// Cancel all uploads
function cancelAll() {
  uploadTasks.forEach(task => task.abort())
}
  1. Upload with progress display:
uni.uploadFile({
  url: 'https://example.com/upload',
  filePath: tempFilePaths[0],
  name: 'file',
  success: () => {
    uni.showToast({ title: 'Upload successful' })
  },
  fail: () => {
    uni.showToast({ title: 'Upload failed', icon: 'error' })
  },
  complete: () => {
    console.log('Upload completed')
  },
  progress: (res) => {
    console.log('Upload progress', res.progress)
    this.progress = res.progress
  }
})

File Download (uni.downloadFile)

uni.downloadFile is used to download file resources from the network to the local device, returning the temporary path of the file. On platforms like WeChat Mini Programs, downloaded files are saved to a temporary directory and require the saveFile API to be permanently saved.

Basic example:

uni.downloadFile({
  url: 'https://example.com/image.jpg',
  success: (res) => {
    if (res.statusCode === 200) {
      console.log('Temporary file path:', res.tempFilePath)
    }
  }
})

The complete process in practical applications typically includes:

  1. Downloading the file
  2. Saving it locally
  3. Handling the save result

Complete example:

uni.downloadFile({
  url: 'https://example.com/report.pdf',
  success: (downloadRes) => {
    if (downloadRes.statusCode === 200) {
      uni.saveFile({
        tempFilePath: downloadRes.tempFilePath,
        success: (saveRes) => {
          const savedFilePath = saveRes.savedFilePath
          uni.showModal({
            content: 'File saved to: ' + savedFilePath,
            showCancel: false
          })
        }
      })
    }
  },
  fail: () => {
    uni.showToast({ title: 'Download failed', icon: 'none' })
  }
})

Common Issues in File Operations

  1. Large file upload optimization:
// Chunked upload implementation
async function chunkUpload(file, chunkSize = 1024 * 1024) {
  const fileSize = file.size
  let offset = 0
  let chunkIndex = 0
  
  while (offset < fileSize) {
    const chunk = file.slice(offset, offset + chunkSize)
    const formData = new FormData()
    formData.append('file', chunk)
    formData.append('chunk_index', chunkIndex)
    formData.append('total_chunks', Math.ceil(fileSize / chunkSize))
    
    await uni.uploadFile({
      url: 'https://example.com/upload_chunk',
      filePath: chunk,
      name: 'chunk',
      formData: formData
    })
    
    offset += chunkSize
    chunkIndex++
  }
  
  // Notify the server to merge chunks
  await uni.request({
    url: 'https://example.com/merge_chunks',
    data: {
      file_name: file.name,
      total_chunks: chunkIndex
    }
  })
}
  1. File download renaming:
// Generate a unique filename using a timestamp
function downloadWithRename(url) {
  const ext = url.split('.').pop()
  const timestamp = new Date().getTime()
  const fileName = `download_${timestamp}.${ext}`
  
  uni.downloadFile({
    url: url,
    success: (res) => {
      uni.saveFile({
        tempFilePath: res.tempFilePath,
        success: (saveRes) => {
          // On iOS, direct renaming is not possible; the file must be saved first and then moved
          uni.getFileSystemManager().saveFile({
            tempFilePath: saveRes.savedFilePath,
            filePath: `${wx.env.USER_DATA_PATH}/${fileName}`,
            success: (finalRes) => {
              console.log('Final save path:', finalRes.savedFilePath)
            }
          })
        }
      })
    }
  })
}
  1. Cross-platform compatibility handling:
// Differentiate handling based on the running platform
function downloadFile(url) {
  // #ifdef H5
  // Use an <a> tag for direct download on H5
  const link = document.createElement('a')
  link.href = url
  link.download = ''
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
  // #endif
  
  // #ifndef H5
  // Use uni.downloadFile on other platforms
  uni.downloadFile({
    url: url,
    success: (res) => {
      // Handle download result
    }
  })
  // #endif
}

Security and Permissions

  1. File upload type restrictions:
uni.chooseImage({
  count: 1,
  sizeType: ['original', 'compressed'],
  sourceType: ['album', 'camera'],
  success: (res) => {
    const file = res.tempFiles[0]
    // Check file type
    const validTypes = ['image/jpeg', 'image/png']
    if (!validTypes.includes(file.type)) {
      return uni.showToast({ title: 'Only JPEG/PNG formats are supported', icon: 'none' })
    }
    
    // Check file size (5MB limit)
    if (file.size > 5 * 1024 * 1024) {
      return uni.showToast({ title: 'File size cannot exceed 5MB', icon: 'none' })
    }
    
    // Upload after validation
    uni.uploadFile({
      url: 'https://example.com/upload',
      filePath: file.path,
      name: 'file'
    })
  }
})
  1. Downloaded file security checks:
uni.downloadFile({
  url: 'https://example.com/file',
  success: (res) => {
    // Check file type
    uni.getFileInfo({
      filePath: res.tempFilePath,
      success: (infoRes) => {
        if (infoRes.digest !== 'expected file hash') {
          return uni.showToast({ title: 'File verification failed', icon: 'none' })
        }
        
        // Open the file after security verification
        uni.openDocument({
          filePath: res.tempFilePath,
          fileType: 'pdf',
          success: () => {
            console.log('Document opened successfully')
          }
        })
      }
    })
  }
})

Performance Optimization Practices

  1. Concurrent upload control:
// Maximum concurrency control
class UploadQueue {
  constructor(maxConcurrent = 3) {
    this.maxConcurrent = maxConcurrent
    this.queue = []
    this.activeCount = 0
  }
  
  add(task) {
    return new Promise((resolve, reject) => {
      this.queue.push({ task, resolve, reject })
      this.next()
    })
  }
  
  next() {
    while (this.activeCount < this.maxConcurrent && this.queue.length) {
      const { task, resolve, reject } = this.queue.shift()
      this.activeCount++
      
      task()
        .then(resolve)
        .catch(reject)
        .finally(() => {
          this.activeCount--
          this.next()
        })
    }
  }
}

// Usage example
const uploadQueue = new UploadQueue(2)
files.forEach(file => {
  uploadQueue.add(() => new Promise((resolve, reject) => {
    uni.uploadFile({
      url: 'https://example.com/upload',
      filePath: file.path,
      name: 'file',
      success: resolve,
      fail: reject
    })
  }))
})
  1. Resumable upload implementation:
// Persist upload state
let uploadState = {
  fileId: null,
  uploadedSize: 0,
  totalSize: 0,
  chunks: []
}

// Resume upload
function resumeUpload() {
  const state = uni.getStorageSync('uploadState') || uploadState
  if (!state.fileId) return
  
  uni.uploadFile({
    url: 'https://example.com/resume_upload',
    filePath: state.filePath,
    name: 'file',
    formData: {
      file_id: state.fileId,
      start_byte: state.uploadedSize
    },
    progress: (res) => {
      const uploaded = state.uploadedSize + res.loaded
      state.uploadedSize = uploaded
      uni.setStorageSync('uploadState', state)
    },
    success: () => {
      uni.removeStorageSync('uploadState')
    }
  })
}
  1. Download caching strategy:
// Download method with caching
const fileCache = {}

function cachedDownload(url) {
  // Check memory cache
  if (fileCache[url]) {
    return Promise.resolve(fileCache[url])
  }
  
  // Check local storage
  return new Promise((resolve, reject) => {
    uni.getSavedFileList({
      success: (res) => {
        const file = res.fileList.find(f => f.filePath.includes(url))
        if (file) {
          fileCache[url] = file.filePath
          return resolve(file.filePath)
        }
        
        // Download if no cache exists
        uni.downloadFile({
          url: url,
          success: (downloadRes) => {
            uni.saveFile({
              tempFilePath: downloadRes.tempFilePath,
              success: (saveRes) => {
                fileCache[url] = saveRes.savedFilePath
                resolve(saveRes.savedFilePath)
              }
            })
          },
          fail: reject
        })
      }
    })
  })
}

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.