Tải tệp lên Dropbox sử dụng CURL và Dropbox API Version 2

Mình sử dụng cách này để tải tệp cần backup hàng ngày lên Dropbox kết hợp từ Crontab, CURL và Dropbox API v2, các bạn có thể đọc tiếp để tham khảo và áp dụng nếu cần.

Chúng ta cần tạo tài khoản Dropbox, có thể đăng nhập qua Google:

  1. Truy cập: https://www.dropbox.com/developers/apps/create tạo tài khoản nếu chưa có hoặc đăng nhập nếu đã có rồi.
  2. Tiếp theo sẽ có 3 bước chúng ta cần hoàn thành để tạo 1 app:
    – Chọn 1 API (thông thường chỉ có 1 – chỉ việc tick chọn là xong)
    – Chọn quyền truy cập cho API
    – Nhập tên app vào tạo app
  3. Sau khi tạo xong thì cần sang tab Permissions để cung cấp quyền upload và download (nếu cần). Trong phần Files and folders tick chọn files.content.write để có quyền upload, tick chọn files.content.read nếu bạn muốn download file qua API nhé. Rồi bấm nút “Submit” để lưu lại (còn các quyền khác các bạn tự tìm hiểu nhé, mình chỉ cần tải tệp lên thì chỉ cần nhiêu đó thôi).
  4. Quay trở lại tab Settings và kéo xuống phần OAuth 2 và để ý phần Access token expiration sẽ có 2 tùy chọn là Short-lived và No expiration. Đối với Short-lived thì access token sẽ chỉ tồn tại ở một khoảng thời gian ngắn, khi hết hạn thì bạn sẽ không thể dùng access token để upload được nữa mà phải generate lại token mới để sử dụng. Đối với No expiration thì ngược lại, nó sẽ không bao giờ hết hạn và mình chọn cái này để đỡ phải generate lại access token.
  5. Bấm Generated access token để tạo access token mới, các bạn lưu lại token này để sử dụng nhé, vì khi refresh lại trang thì nó sẽ biến mất. Trường hợp quên hoặc thất lạc token thì cứ vào gen lại cái mới rồi sử dụng bình thường.
  6. Các thông số khác thì các bạn tự đọc nhé vì mình làm vài bước trên là đã có thể upload được rồi nên mình bỏ qua các phần còn lại.

Sau khi có access token của Dropbox API thì giờ có thể tải file lên bằng URL:

Tải lên:

curl -X POST https://content.dropboxapi.com/2/files/upload \
     --header "Authorization: Bearer DROPBOX_ACCESS_TOKEN" \
     --header "Dropbox-API-Arg: {\"path\": \"DROPBOX_STORE_PATH\", \"mode\": \"overwrite\"}" \
     --header "Content-Type: application/octet-stream" \
     --data-binary "@/path/to/file"

Giải thích: DROPBOX_ACCESS_TOKEN là access token chúng ta lấy từ các bước trên, DROPBOX_STORE_PATH là đường dẫn lưu trữ trên Dropbox (ví dụ /home/upload/test.txt thì các bạn có thể check trên thư mục dropbox home -> upload -> test.txt), “/path/to/file” là đường dẫn file cần tải lên (ví dụ: /home/pi/test.txt). Mình để modeoverwrite => nó sẽ thay thế (ghi đè file) nếu đã tồn tại đường dẫn DROPBOX_STORE_PATH trên Dropbox của bạn.

Ví dụ tải lên:

curl -X POST https://content.dropboxapi.com/2/files/upload \
     --header "Authorization: Bearer o_dresR9ZLsAAAAAAAAAASrU2e8NUcohmbX2cRw7StrYsng_8-beW2qOQXWyWiJK" \
     --header "Dropbox-API-Arg: {\"path\": \"/home/myapp/backup.zip\", \"mode\": \"overwrite\"}" \
     --header "Content-Type: application/octet-stream" \
     --data-binary "@/home/pi/backup.zip"

Tải xuống:

curl -X POST https://content.dropboxapi.com/2/files/download \
     --header "Authorization: Bearer DROPBOX_ACCESS_TOKEN" \
     --header "Dropbox-API-Arg: {\"path\": \"DROPBOX_STORE_PATH\"}" \
     -o "/path/to/save"

Giải thích: “/path/to/save” là đường dẫn sẽ lưu file tải về ở máy của bạn.

Ví dụ tải xuống:

curl -X POST https://content.dropboxapi.com/2/files/download \
     --header "Authorization: Bearer o_dresR9ZLsAAAAAAAAAASrU2e8NUcohmbX2cRw7StrYsng_8-beW2qOQXWyWiJK" \
     --header "Dropbox-API-Arg: {\"path\": \"/home/myapp/backup.zip\"}" \
     -o "/home/pi/backup_downloaded.zip"

Chúng ta có thể thêm lệnh upload hoặc download vào 1 file .sh rồi thêm vào crontab để thực hiện việc upload hoặc download một cách tự động.

Copy file lên server sử dụng SCP

Khi làm việc với các server Linux thông qua SSH chắc hẳn ai cũng sẽ có lúc cần đưa một vài tệp tin nào đó lên server. Ngoài một số tools cho phép upload file bằng giao diện trực quan, chỉ cần vài click hoặc kéo thả thì chúng ta có thể đưa tệp lên server bằng dòng lệnh sử dụng SCP (secure copy).

Cú pháp như sau:

# scp source_file_path ssh_username@ssh_host:target_file_path

Trong đó:

source_file_path: là đường dẫn của tệp trên máy của bạn cần đưa lên server.

ssh_username: là username ssh của bạn, ví dụ: root.

ssh_host: là địa chỉ máy chủ SSH của bạn, có thể là IP, tên miền.

target_file_path: là đường dẫn tới thư mục trên server mà bạn muốn đưa tệp lên.

Ví dụ mình sẽ đưa tệp test.zip ở ổ C trong Windows lên server có địa chỉ IP là 192.168.0.106 với SSH user là root, nơi lưu trữ tệp này trên server sẽ là /u01/upload, mình dùng PowerShell thì dòng lệnh sẽ như sau:

> scp C:\test.zip root@192.168.0.106:/u01/upload

Sau khi gõ lệnh, khi bạn nhấn phím Enter thì sẽ có yêu cầu nhập password của user root, nhập đúng pass quá trình upload sẽ được thực hiện.

Xử lý khi làm việc với SSL trong Java

Khi bạn làm việc với 1 server chạy SSL tương tác bằng Java thì nếu không được server tin tưởng bạn sẽ không thể làm việc tiếp được, dưới đây là một ví dụ về 1 class có tên SSLHandler.java có thể tham khảo để xử lý một số ngoại lệ khi làm việc với SSL trong Java.

Để làm được trước hết ta cần 1 file keystore hoặc #PKCS12, ví dụ với 1 Web server chạy SSL thì chỉ cần truy cập website tải chứng thư SSL của website về dưới dạng file .cer hoặc .crt sau đó dùng keytool của Java để đóng JKS, mình thường làm vậy.
Ở đây mình code Maven project nên sẽ đặt file example.jks trong thư mục src/main/resources, đường dẫn sẽ như sau src/main/resources/example.jks.

Tại đây mình cũng tạo một file truststoreconfig.properties và đường dẫn của nó như sau src/main/resources/truststoreconfig.properties.

File truststoreconfig.properties có nội dung dạng như sau:

ssl.trustStore=example.jks
ssl.trustStorePassword=123456
ssl.trustStoreType=JKS

File SSLHandler.java có nội dung dạng như sau:

package applications.util;

import java.io.File;
import java.io.InputStream;
import java.util.Properties;

/**
 * 
 * SSLHandler
 */
public class SSLHandler {

    private static final String trustStore;
    private static final String trustStorePassword;
    private static final String trustStoreType;
    
    // load properties file
    static {
        Properties props = new Properties();
        InputStream is = null;
        
        try {
            is = Thread.currentThread().getContextClassLoader()
                    .getResourceAsStream("truststoreconfig.properties");
            if (is == null) {
                throw new RuntimeException("Cannot read truststoreconfig.properties file!");
            }
            
            props.load(is);
            trustStore = props.getProperty("ssl.trustStore");
            trustStorePassword = props.getProperty("ssl.trustStorePassword");
            trustStoreType = props.getProperty("ssl.trustStoreType");
        } catch (Exception e) {
            throw new RuntimeException("Cannot read truststoreconfig.properties file! detail:\r\n" + e);
        }
    }
    
    private static String _getTrustStorePath() {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        File file = new File(classLoader.getResource("truststoreconfig.properties").getFile());
        
        return file.getParentFile().getAbsolutePath();
    }
    
    /**
     * 
     * setSSL
     */
    public static void setSSL() {
        System.setProperty("javax.net.ssl.trustStore", _getTrustStorePath());
        System.setProperty("javax.net.ssl.trustStorePassword", trustStorePassword);
        System.setProperty("javax.net.ssl.trustStoreType", trustStoreType);
    }
    
}

Để sử dụng trước khi trao đổi với server chạy SSL chỉ cần gọi hàm setSSL trước xử lý của bạn:

SSLHandler.setSSL();
...

Tự động tải lại trang web sau khoảng thời gian không thao tác

Xin chào các bạn, trong bài viết này mình chia sẻ cho các bạn cách làm thế nào để tự động tải lại trang web khi mà người dùng truy cập trang đó không có bất kỳ hoạt động nào trên trang trong một khoảng thời gian nhất định. Ví dụ: 10 phút (không hề có lần di chuyển con trỏ chuột, click chuột, hay nhấn phím, … trên trang) thì ta sẽ tải lại trang đó.

Code Javascript

/* Auto refresh the page when user no activity for few seconds, using Javascript */
 
function setIdle(seconds, callback) {
    var timer,
        interval = (seconds * 1000);
    function refresh() {
        // Reset timer
        clearTimeout(timer);
        // Set timer
        timer = setTimeout(callback, interval);
    }
    // Add event to set timeout
    window.addEventListener("mousemove", refresh, true);
    window.addEventListener("click", refresh, true);
    window.addEventListener("keypress", refresh, true);
    // Invoke function "refresh" for first time
    refresh();
}
 
// Example, invoke function "setIdle"
setIdle(20, function() {
    window.location.reload(true);
});

Demo

Các bạn copy toàn bộ đoạn code trên thêm vào thẻ <script> trên trang web mà các bạn cần tải lại và sửa lại tham số 20 ở hàm setIdle nhé, mình để 20 ở đây có nghĩa là 20s. Ví dụ các bạn muốn để thời gian là 15 phút thì truyền 900 (60 * 15 = 900🙂 ), như vậy là cứ mỗi 15 phút mà người truy cập không có bất kỳ thao tác, hoạt động nào trên trang web, trang đó sẽ được tải lại.

Tránh spam server khi dùng keyup, keydown

Chắc hẳn khi bạn làm một thẻ input nhập nội dung để tìm kiếm và không cần nút bấm để submit, vậy thì việc submit sẽ là tự động sau khi nhập bất kỳ ký tự nào vào thẻ input. Khi này thì sẽ dùng sự kiện thích hợp nhất sẽ là keyup hoặc keydown của jQuery, mọi thứ đều diễn ra bình thường và gần như kết quả sẽ trả về ngay lập tức cho bạn. Nhưng có một vấn đề ở đây là bạn có chắc sau khi nhập các ký tự thì chỉ có duy nhất 1 request gửi đến server? Không! mỗi khi bạn nhập 1 bất kỳ thì sẽ là 1 lần gửi request đến server, việc này thật sự rất nghiêm trọng!

Sau đây là đoạn code mình dùng timeout của Javascript để xử lý chỉ gửi duy nhất 1 lần request đến server nhập xong từ khóa tìm kiếm.

Mã Javascript:

<script type="text/javascript">
    var timeout = null;
    $('#keyword').on('keyup keydown keypress', function(e) {
        // xóa sự kiện timeout lưu trước đó
        clearTimeout(timeout);
  
        timeout = setTimeout(function() {
            alert('Xử lý gửi dữ liệu lên server ở đây');
        }, 1000);
    });
</script>